package net.sh.dpinfrastructure.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import net.sh.dpinfrastructure.config.DPConfig;
import net.sh.dpinfrastructure.exception.DPException;
import net.sh.dpinfrastructure.log.DPLogger;


/**
 * 
 * {@link net.sh.dpinfrastructure.http.DPHttp}基于{@link OKHttp}的实现类
 * 
 * @version 1.0
 * @since JDK1.7
 * @author shaohui
 * @company 上海朝阳永续信息技术有限公司
 * @copyright (c) 2016 SunTime Co'Ltd Inc. All rights reserved.
 * @date 2016年8月10日 下午3:46:30
 */
public class DPOKHttp implements DPHttp {
    
    private static final DPLogger LOGGER = new DPLogger(DPHttp.class);

    private final OkHttpClient client;
    
    public DPOKHttp(DPConfig config) {
        client = new OkHttpClient();
        LOGGER.debug("http服务初始化成功");
    }
    
    /**
     * 
     * 添加header
     *
     * @param requestBuilder
     * @param headerMap
     * 
     * @author shaohui
     * @date 2016年8月11日 下午3:39:23
     */
    private void appendHeader(Request.Builder requestBuilder, Map<String, String> headerMap) {
        if (MapUtils.isEmpty(headerMap)) {
            return;
        }
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            String headName = entry.getKey();
            String headValue = entry.getValue();
            if (StringUtils.isBlank(headName) || StringUtils.isBlank(headValue)) {
                continue;
            }
            try {
                requestBuilder.addHeader(headName, URLEncoder.encode(headValue, "utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 
     * 构建request body
     *
     * @param params
     * @return
     * 
     * @author shaohui
     * @date 2016年8月11日 下午4:05:37
     */
    private RequestBody createRequestBody(Map<String, String> params) {
        FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
        if (MapUtils.isEmpty(params)) {
            return formEncodingBuilder.build();
        }
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String paramName = entry.getKey();
            if (StringUtils.isBlank(paramName)) {
                continue;
            }
            formEncodingBuilder.add(paramName, entry.getValue());
        }
        return formEncodingBuilder.build();
    }

    @Override
    public DPHttpResponse delete(String url) {
        return delete(url, null, null);
    }

    @Override
    public DPHttpResponse delete(String url, Map<String, String> params) {
        return delete(url, null, params);
    }

    @Override
    public DPHttpResponse delete(String url, Map<String, String> headParams, Map<String, String> params) {
        return request(DPHttpRequestMethod.DELETE, url, headParams, params);
    }

    @Override
    public DPHttpResponse get(String url) {
        return get(url, null, null);
    }

    @Override
    public DPHttpResponse get(String url, Map<String, String> params) {
        return get(url, null, params);
    }

    @Override
    public DPHttpResponse get(String url, Map<String, String> headParams, Map<String, String> params) {
        return request(DPHttpRequestMethod.GET, url, headParams, params);
    }

    @Override
    public DPHttpResponse post(String url) {
        return post(url, null, null);
    }

    @Override
    public DPHttpResponse post(String url, Map<String, String> params) {
        return post(url, null, params);
    }
    
    @Override
    public DPHttpResponse post(String url, Map<String, String> headParams, Map<String, String> params) {
        return request(DPHttpRequestMethod.POST, url, headParams, params);
    }

    @Override
    public DPHttpResponse put(String url) {
        return put(url, null, null);
    }

    @Override
    public DPHttpResponse put(String url, Map<String, String> params) {
        return put(url, null, params);
    }

    @Override
    public DPHttpResponse put(String url, Map<String, String> headParams, Map<String, String> params) {
        return request(DPHttpRequestMethod.PUT, url, headParams, params);
    }

    @Override
    public DPHttpResponse request(DPHttpRequestMethod requestType, String url, Map<String, String> headParams,
                                  Map<String, String> params) {
        Request.Builder requestBuilder = new Request.Builder();
        if (requestType == DPHttpRequestMethod.GET || requestType == DPHttpRequestMethod.DELETE) {
            requestBuilder.url(DPHttp.createUrlWithParams(url, params));
        } else {
            requestBuilder.url(url);
        }
        appendHeader(requestBuilder, headParams);
        switch (requestType) {
            case GET: {
                requestBuilder.get();
                break;
            }
            case POST: {
                requestBuilder.post(createRequestBody(params));
                break;
            }
            case PUT: {
                requestBuilder.put(createRequestBody(params));
                break;
            }
            case DELETE: {
                requestBuilder.delete(createRequestBody(params));
                break;
            }
            default: {
                throw new DPException("不支持的http请求类型");
            }
        }
        Request request = requestBuilder.build();
        try {
            Response response = client.newCall(request).execute();
            DPHttpResponse dpHttpResponse = new DPHttpResponse();
            dpHttpResponse.setCode(response.code());
            dpHttpResponse.setLength(response.body().contentLength());
            dpHttpResponse.setContent(response.body().bytes());
            return dpHttpResponse;
        } catch (IOException e) {
            throw new DPException("http请求失败", e);
        }
    }
}
